<?php

namespace slinks\extensions\action\interceptor;

use slinks\core\DependencyInjection\IDumpsArgument;
use slinks\core\DependencyInjection\ContainerInterface;

/**
 * Contains a list of interceptors. 
 * 
 * @author Navid Mitchell
 *
 */
class InterceptorStack implements \ArrayAccess, \Iterator, \Countable, IDumpsArgument {
    /* @var $name string name of this interceptor stack */

    private $name;

    /* @var $interceptorReferences array of interceptor service id's */
    private $interceptorReferences;

    /* @var $container ContainerInterface contains the interceptor services */
    private $container;

    /**
     * Construct a new InterceptorStack 
     * @param string $name the name of this InterceptorStack
     * @param ContainerInterface $container must contain the actual IActionInterceptor implementations.
     * @param array $interceptorReferences contains the serviceId's for the IActionInterceptor in this stack.
     */
    public function __construct($name, ContainerInterface $container, $interceptorReferences) {
        $this->name = $name;
        $this->container = $container;
        $this->interceptorReferences = $interceptorReferences;
    }

    public function getName() {
        return $this->name;
    }

    public function offsetSet($offset, $value) {
        throw new \LogicException('You can\'t set a interceptor.');
    }

    public function offsetExists($offset) {
        return isset($this->interceptorReferences[$offset]);
    }

    public function offsetUnset($offset) {
        throw new \LogicException('You can\'t unset a interceptor.');
    }

    public function offsetGet($offset) {
        $ret = null;
        if (isset($this->interceptorReferences[$offset])) {
            $ret = $this->getInterceptorFromContainer($this->interceptorReferences[$offset]);
        }
        return $ret;
    }

    public function rewind() {
        reset($this->interceptorReferences);
    }

    public function current() {
        $current = current($this->interceptorReferences);
        if ($current !== false) {
            $current = $this->getInterceptorFromContainer($current);
        }
        return $current;
    }

    public function key() {
        return key($this->interceptorReferences);
    }

    public function next() {
        $next = next($this->interceptorReferences);
        if ($next !== false) {
            $next = $this->getInterceptorFromContainer($next);
        }
        return $next;
    }

    public function valid() {
        return $this->current() !== false;
    }

    public function count() {
        return count($this->interceptorReferences);
    }

    public function getArgumentString() {
        $ret = "new slinks\extensions\action\interceptor\InterceptorStack('{$this->name}', \$this, array(";
        $i = 0;
        foreach ($this->interceptorReferences as $ref) {
            if ($i > 0) {
                $ret .= ', ';
            }
            $ret .= '\'' . $ref . '\'';
            $i++;
        }
        $ret .= '))';
        return $ret;
    }

    private function getInterceptorFromContainer($interceptorName) {
        $ret = $this->container->get($interceptorName);
        if ($ret == null) {
            throw new Exception('Cannot find Interceptor for name ' . $interceptorName);
        }
        return $ret;
    }

}